; naskfunc
; TAB=4

[FORMAT "WCOFF"]                	; 制作目标文件的模式
[INSTRSET "i486p"]			; 告诉nask这个程序是给486用的（486：intel 32位处理器）
[BITS 32]                       	; 制作32位模式用的机器语言

; 制作目标文件的信息	

[FILE "naskfunc.nas"]           	; 源文件名信息

        GLOBAL	_io_hlt, _io_cli, _io_sti, _io_stihlt
        GLOBAL  _io_in8, _io_in16, _io_in32
        GLOBAL  _io_out8, _io_out16, _io_out32
        GLOBAL  _io_load_eflags, _io_store_eflags

; 以下是实际的函数

[SECTION .text]					; 目标文件中写了这些之后再写程序

_io_hlt:       					; void io_hlt(void);
        HLT	
        RET    					; RET - return

_io_cli:       					; void io_cli(void);
        CLI
        RET

_io_sti:						; void io_sti(void);
        STI
        RET

_io_stihlt:						; void io_stihlt(void);
        STI
        HLT
        RET

_io_in8:						; int io_in8(int port);
        MOV     EDX,[ESP+4]     ; port
        MOV     EAX,0
        IN      AL,DX
        RET

_io_in16:						; int io_in16(int port);
        MOV     EDX,[ESP+4]     ; port
        MOV     EAX,0
        IN      AX,DX
		RET

_io_in32:						; int io_in32(int port);
        MOV     EDX,[ESP+4]     ; port
		IN		EAX,DX
		RET

_io_out8:						; void io_out8(int port, int data);
		MOV		EDX,[ESP+4]		; port
		MOV		AL,[ESP+8]		; data
		OUT		DX,AL
		RET

_io_out16:						; void io_out16(int port, int data);
		MOV		EDX,[ESP+4]		; port
		MOV		EAX,[ESP+8]		; data
		OUT		DX,AX
		RET

_io_out32:						; void io_out32(int port, int data);
		MOV		EDX,[ESP+4]		; port
		MOV		EAX,[ESP+8]		; data
		OUT		DX,EAX
		RET

; 能够用来读写EFLAGS的，只有PUSHFD和POPFD指令
_io_load_eflags:				; int io_load_eflags(void);
		PUSHFD					; PUSHFD - 将标志位的值按双字长压入栈push flags double-word，它做的就是PUSH EFLAGS
		POP		EAX				; PUSHFD POP EAX这两句相当于MOV EAX,EFLAGS，首先将EFLAGS压入栈，再将弹出的值代入EAX
		RET						; 根据C语言的规约，执行RET语句时，EAX中的值就被看做是函数的返回值

_io_store_eflags:				; void io_store_eflags(int eflags);
		MOV		EAX,[ESP+4]		; eflags
		PUSH	EAX				; PUSH EAX POPFD这两句相当于MOV EFLAGS,EAX，首先将EAX压入栈再将EFLAGS弹出获取EAX值（自己的理解）
		POPFD					; POPFD - 按双字长将标志位从栈弹出pop flags double-word，它做的就是POP EFLAGS
		RET